package top.riske.animalhazardassessment.common.http.response;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;
import top.riske.animalhazardassessment.common.http.exception.BusinessException;

import java.util.List;


/**
 * 统一包装所有响应结果
 * 处理所有http状态码，使状态码=Result.code
 */
@Slf4j
@ControllerAdvice
public class HttpControllerResponseAdvice implements ResponseBodyAdvice<Object> {

    private static final ObjectMapper objectMapper = new ObjectMapper();

    /**
     * 避免处理swagger文档
     */
    private final List<String> swaggerClasses = List.of(new String[]{"org.springdoc.webmvc.api.OpenApiWebMvcResource",
            "org.springdoc.webmvc.ui.SwaggerConfigResource",
            "org.springdoc.webmvc.api.OpenApiWebMvcResource"
    });

    /**
     * 判断是否需要处理，都需要处理
     */
    @Override
    public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) {
        if(swaggerClasses.contains(returnType.getDeclaringClass().getName())){
            return false;
        }
        return true;
    }

    /**
     * 包装返回值为Result.data
     */
    @Override
    public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class<? extends HttpMessageConverter<?>> selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {;
        // 业务异常的情况
        if(body instanceof BusinessException businessException) {
            return Result.fail()
                    .code(businessException.getStatus())
                    .message(businessException.getMessage());
        }

        // 未指定响应格式时
        if(response.getHeaders().getContentType() == null) {
            if(body instanceof String){
                // string类型需要手动序列化
                try {
                    response.getHeaders().setContentType(MediaType.APPLICATION_JSON);
                    return objectMapper.writeValueAsString(Result.success(body));
                } catch (JsonProcessingException e) {
                    throw new RuntimeException("无法处理json格式", e);
                }
            }else{
                return Result.success(body);
            }
        }
        return body;
    }
}
